import random
import re

from django import http
from django.conf import settings
from django.contrib.auth import login
from django.shortcuts import render, redirect

from django.views.generic.base import View
from QQLoginTool.QQtool import OAuthQQ
from django_redis import get_redis_connection
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_jwt.settings import api_settings

from carts.utils import merge_cart
from meiduo_mall.utils import meiduo_signature
from meiduo_mall.utils.response_code import RETCODE

# 请求QQ授权
from meiduo_mall.utils.sinaweibopy3_master import sinaweibopy3
from oauth import constants
from oauth.models import OAuthQQUser, OAuthSinaUser
# from oauth.serializers import OAuthSinaUserSerializer
from oauth.serializers import OauthsinaSerializers
from users.models import User
from itsdangerous import TimedJSONWebSignatureSerializer as TJS


class OauthQQUrlView(View):
    def get(self, request):
        # next表示从哪个页面进入到的登录页面，将来登录成功后，就自动回到那个页面
        next = request.GET.get('next')
        # 初始化OAuthQQ对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=next)
        # 获取QQ登录扫码页面，扫码后得到AuthorizationCode
        login_url = oauth.get_qq_url()
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})


# QQ授权回调
class QQAuthUserView(View):
    """用户扫码登录的回调处理"""

    def get(self, request):
        """Oauth2.0认证"""
        # 接收Authorization Code
        code = request.GET.get('code')
        state = request.GET.get('state', '/')
        if not code:
            return http.HttpResponseForbidden('缺少code')
        # 创建工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)

        # 1.根据code获取token
        token = oauth.get_access_token(code)

        # 2.根据token获取openid
        openid = oauth.get_open_id(token)

        # 判断是否初次授权
        try:
            qquser = OAuthQQUser.objects.get(openid=openid)
        except:
            # 未查到数据，则为初次授权，显示绑定页面
            # 将openi加密
            json_str = meiduo_signature.dumps({"openid": openid}, constants.OPENID_EXPIRES)
            # 显示绑定页面
            context = {
                'token': json_str
            }
            return render(request, 'oauth_callback.html', context)
        else:
            # 查询到授权对象，则状态保持，转到相关页面
            user = qquser.user
            login(request, user)

            response = redirect(state)
            response.set_cookie('username', user.username)
            return response

    def post(self, request):
        # 接收：openid,mobile,password,sms_code
        access_token = request.POST.get('access_token')
        mobile = request.POST.get('mobile')
        password = request.POST.get('pwd')
        pic_code = request.POST.get('pic_code')
        sms_code = request.POST.get('sms_code')
        state = request.GET.get('state', '/')

        # 验证注册参数
        openid_dict = meiduo_signature.loads(access_token, constants.OPENID_EXPIRES)
        if openid_dict is None:
            return http.HttpResponseForbidden('openid无效，请重新填写openid')
        openid = openid_dict.get('openid')
        # 处理：初次授权，完成openid与user的绑定
        # 1.判断手机号是否已经使用
        try:
            user = User.objects.get(mobile=mobile)
        except:
            # 如果未使用，则新建用户
            user = User.objects.create_user(mobile, password=password, mobile=mobile)
        else:
            # 如果已使用，则验证密码
            # 密码正确，则继续执行
            if not user.check_password(password):
                return http.HttpResponseForbidden('手机号已使用，或密码错误')

            # 绑定 ： 新建QAuthUser对象

        qquser = OAuthQQUser.objects.create(
            user=user,
            openid=openid
        )
        # 状态保持
        login(request, user)
        response = redirect(state)
        # 合并购物车
        response = merge_cart(request, response)
        return response


# class OAuthSinaURLView(APIView):
#     """
#     提供QQ登录的网址
#     前端请求的接口网址  /oauth/sina/authorization/?state=xxxxxxx
#     state参数是由前端传递，参数值为在sina登录成功后，我们后端把用户引导到哪个美多商城页面
#     """
#
#     def get(self, request):
#         # 提取state参数
#         state = request.query_params.get('state')
#         if not state:
#             state = '/'  # 如果前端未指明，我们设置用户sina登录成功后，跳转到主页
#             # return redirect('/')
#
#         # 按照sina的说明文档，拼接用户sina登录的链接地址
#         # 3、创建qq对象
#         wb = sinaweibopy3.APIClient(app_key=settings.SINA_KEY, app_secret=settings.SINA_APP_SECRET,
#                                     redirect_uri=settings.SINA_REDIRECT_URI, )
#         url = wb.get_authorize_url()
#         # 4、构建跳转连接
#         print(url)
#         # login_url = webbrowser.open_new(url)
#
#         # 5、返回跳转连接
#         return Response({'oauth_url': url})
#
#
# class OAuthSinaUserView(APIView):
#     def get(self, request):
#         # 提取code参数
#         code = request.query_params.get('code')
#         if not code:
#             return Response({"errors": "缺少code"}, status=status.HTTP_400_BAD_REQUEST)
#         wb = sinaweibopy3.APIClient(app_key=settings.SINA_KEY, app_secret=settings.SINA_APP_SECRET,
#                                     redirect_uri=settings.SINA_REDIRECT_URI)
#         access_token = wb.request_access_token(code)
#         access_token = access_token['access_token']
#         try:
#             wb_user = OAuthSinaUser.objects.get(access_token=access_token)
#         except:
#             tjs = TJS(settings.SECRET_KEY, 300)
#             access_token = tjs.dumps({'access_token': access_token}).decode()
#             return Response({'access_token': access_token})
#         else:
#             user = wb_user.user
#             jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
#             jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
#
#             payload = jwt_payload_handler(user)
#             token = jwt_encode_handler(payload)
#             return Response({
#                 'token': token,
#                 'username': user.username,
#                 'user_id': user.id,
#             })
#
#     def post(self, request):
#         data = request.data
#         ser = OAuthSinaUserSerializer(data=data)
#         ser.is_valid(raise_exception=True)
#         print(ser.errors)
#         ser.save()
#         return Response(ser.data)

# 微博跳转
class OauthsinaloginView(APIView):
    # 构建跳转链接
    def get(self, request):
        state = request.query_params.get('next', None)
        # 2.判断前段是否传递验证字符串数据
        if not state:
            state = '/'
        # APP_KEY = '3305669385'
        # APP_SECRET = '74c7bea69d5fc64f5c3b80c802325276'
        # REDIRECT_URL = 'http://www.meiduo.site:8080/sina_callback.html'
        APP_KEY = '3935468527'
        APP_SECRET = 'f71e1c17bbc762ff2464f323f667af64'
        REDIRECT_URL = 'http://www.meiduo.site:8080/sina_callback.html'

        # step 2 : get authorize url and code

        sina_url = sinaweibopy3.APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri=REDIRECT_URL)
        login_url = sina_url.get_authorize_url()
        return Response({'login_url': login_url})


# 新浪绑定和登陆
class OauthSInaView(APIView):
    def get(self,request):
        #获取
        # 1，获取code值
        code = request.query_params.get('code', None)
            #判断是否获取code值
        if not code:
            return Response({'message': 'code缺失'}, status=400)

        # 2，通过code值获取access_token
        # 新浪返回的token，类似abc123xyz456，每天的token不一样
        APP_KEY = '3305669385'
        APP_SECRET = '74c7bea69d5fc64f5c3b80c802325276'
        REDIRECT_URL = 'http://www.meiduo.site:8080/sina_callback.html'
        sina = sinaweibopy3.APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri=REDIRECT_URL)
        r = sina.request_access_token(code)
        access_token = r.access_token
        expires_in = r.expires_in  # token过期的UNIX时间
        try:
            sina_user = OAuthSinaUser.objects.get(openid=access_token)
        except:
            # 5，未绑定，则进入到绑定页面完成绑定
            tjs= TJS(settings.SECRET_KEY, 300)
            open_id = tjs.dumps({'openid':access_token}).decode()
            return Response({'access_token': open_id})
        # 6，绑定过，则登录成功
        else:
            user = sina_user.user
            # 生成JWT_token值
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

            payload = jwt_payload_handler(user)  # 生成荷载部分
            token = jwt_encode_handler(payload)  # 生成token
            response = Response({
                'token': token,
                'username': user.username,
                'user_id': user.id
            })

            # 合并购物车
            response = merge_cart(request, response)

        return response

    def post(self, request):
        '''
        1/获取前端传递的参数mobile，password，sms_code，image_code,access_token  json格式
        2/检查参数完整性  序列化器
        3/检查参数的格式  序列化器
        4/保存到数据库  序列化器
        5/把id，username，token返回前端
        '''
        # 获取前端数据
        data = request.data
        # 进行验证
        ser = OauthsinaSerializers(data=data)
        ser.is_valid()
        ser.save()

        return Response(ser.data)